package com.eastfair.pay.chinaums.BScanC;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

/**
 * @author kkqiao
 * b扫c交易退款接口
 * 说明：
 * 进行POS通交易退款操作
 *  测试环境：http://58.247.0.18:29015/v2/poslink/transaction/refund
 *  生产环境：https://api-mop.chinaums.com/v2/poslink/transaction/refund
 */
public class Refund {

    static String appid = "10037e6f6823b20801682b6a5e5a0006";
    static String appkey = "1c4e3b16066244ae9b236a09e5b312e8";
    static String url = "https://test-api-open.chinaums.com/v2/poslink/transaction/refund";

    public static void main(String[] args) throws Exception{
        //1. 组建请求报文
        RefundBody reqBody = new RefundBody();
        reqBody.merchantCode = "123456789900081";
        reqBody.terminalCode = "00810001";
        reqBody.originalOrderId = "20190726150502000021638804";
        reqBody.refundRequestId = reqBody.originalOrderId + "500";
        reqBody.transactionAmount = "1";
        System.out.println("request body:\n"+reqBody);

        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(appid,appkey,"20190729162400","nonce",reqBody.toString());
        System.out.println("authorization:\n"+authorization);

        //3. 发送http请求，并解析返回信息
        String response = request(url,authorization,reqBody.toString());
        System.out.println("response:\n"+response);
    }

    /**
     * 发送http请求
     * @param url 请求url
     * @param authorization 认证报文
     * @param reqBody  请求体
     * @return response
     */
    static String request(String url, String authorization, String reqBody){
        String response = "";
        PrintWriter out = null;
        BufferedReader in = null;
        try{
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            HttpURLConnection httpUrlConnection = (HttpURLConnection) conn;
            httpUrlConnection.setRequestProperty("Content-Type", "application/json");
            httpUrlConnection.setRequestProperty("authorization",authorization);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setDoInput(true);
            out = new PrintWriter(httpUrlConnection.getOutputStream());
            out.write(reqBody);
            out.flush();
            httpUrlConnection.connect();
            in = new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                response += line;
            }
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (out != null) { out.close();}
                if (in != null) {in.close();}
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 获取签名头
     * @param appid
     * @param appkey
     * @param timestamp 格式:"yyyyMMddHHmmss"
     * @param nonce 随机字符串，
     * @param body 请求体
     * @return authorization 认证报文
     * @throws Exception
     */
    static String getAuthorization(String appid, String appkey, String timestamp, String nonce, String body) throws Exception {
        byte[] data = body.getBytes("utf-8");
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid+timestamp+nonce+testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes("utf-8"),"HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes("utf-8"));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return  "OPEN-BODY-SIG AppId="+"\""+appid+"\""+", Timestamp="+"\""+timestamp+"\""+", Nonce="+"\""+nonce+"\""+", Signature="+"\""+localSignatureStr+"\"";
    }

    static class RefundBody{
        //商户号
        String merchantCode;
        //终端号
        String terminalCode;
        //商户订单号
        String merchantOrderId;
        //银商订单号
        String originalOrderId;
        //退款请求标识
        String refundRequestId;
        //交易金额
        String transactionAmount;
        //是否限制跨终端
        String limitCrossDevice;
        //商户冗余信息
        String srcReserved;
        //商品信息
        List<GoodsItem> goods;
        //门店号
        String storeId;
        //操作员编号
        String operatorId;
        //业务标识
        String bizIdentifier;

        String toJson(){
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            if (this.merchantCode != null) sb.append("\"merchantCode\":\"" + this.merchantCode + "\",");
            if (this.terminalCode != null) sb.append("\"terminalCode\":\"" + this.terminalCode + "\",");
            if (this.merchantOrderId !=null) sb.append("\"merchantOrderId\":\"" + this.merchantOrderId + "\",");
            if (this.originalOrderId != null) sb.append("\"originalOrderId\":\"" + this.originalOrderId + "\",");
            if (this.refundRequestId != null) sb.append("\"refundRequestId\":\"" + this.refundRequestId + "\",");
            if (this.transactionAmount != null) sb.append("\"transactionAmount\":\"" + this.transactionAmount + "\",");
            if (this.limitCrossDevice != null) sb.append("\"limitCrossDevice\":\"" + this.limitCrossDevice + "\",");
            if (this.srcReserved != null) sb.append("\"srcReserved\":\"" + this.srcReserved + "\",");
            if (this.goods != null && this.goods.size()>0) {
                sb.append("\"goods\":[");
                for(int i=0;i<goods.size();i++){
                    sb.append(goods.get(i));
                    sb.append(",");
                }
                if (sb.charAt(sb.length() - 1) == ',')
                    sb.deleteCharAt(sb.length() - 1);
                sb.append("],");
            }
            if (this.storeId != null) sb.append("\"storeId\":\"" + this.storeId + "\",");
            if (this.operatorId != null) sb.append("\"operatorId\":\"" + this.operatorId + "\",");
            if (this.bizIdentifier != null) sb.append("\"bizIdentifier\":\"" + this.bizIdentifier + "\",");
            if (sb.charAt(sb.length() - 1) == ',')
                sb.deleteCharAt(sb.length() - 1);
            sb.append("}");
            return sb.toString();
        }

        public String toString(){
            return this.toJson();
        }

        static class GoodsItem {
            //商品ID
            String goodsId;
            //商品名称
            String goodsName;
            //商品数量
            String quantity;
            //商品单价（分）
            String price;
            //商品分类
            String goodsCategory;
            //商品说明
            String body;
            //商品折扣
            String discount;

            String toJson(){
                StringBuilder sb = new StringBuilder();
                sb.append("{");
                if(this.goodsId!=null) sb.append("\"goodsId\":\""+this.goodsId+"\",");
                if(this.goodsName!=null) sb.append("\"goodsName\":\""+this.goodsName+"\",");

                if(this.quantity!=null){
                    sb.append("\"quantity\":\""+this.quantity+"\",");
                }
                if(this.price!=null){
                    sb.append("\"price\":\""+this.price+"\",");
                }
                if(this.goodsCategory!=null){
                    sb.append("\"goodsCategory\":\""+this.goodsCategory+"\",");
                }
                if(this.body!=null){
                    sb.append("\"body\":\""+this.body+"\",");
                }
                if(this.discount!=null){
                    sb.append("\"discount\":\""+this.discount+"\",");
                }
                if(sb.charAt(sb.length()-1) == ',')
                    sb.deleteCharAt(sb.length()-1);
                sb.append("}");
                return sb.toString();
            }
            public String toString(){
                return this.toJson();
            }
        }
    }

}
